
package rendi456.structure.grid;

import java.util.ArrayList;

public class Grid<E extends GridCell>
{
	public final int row;
	public final int col;
	public final int size;
	private final ArrayList<E> nodes;

	private int iterator = 0;

	/**
	 * 
	 * @param row rows
	 * @param col columns
	 */
	public Grid(int row, int col)
	{
		if (row > 0 && col > 0)
		{
			this.row = row;
			this.col = col;
			this.size = row * col;

			this.nodes = new ArrayList<E>(this.size);

			for (int i = 0; i < this.size; i++)
			{
				this.nodes.add(null);
			}
		}
		else
		{
			throw new GridException("construction incorrecte");
		}
	}

	public int getRowCount()
	{
		return this.row;
	}

	public int getColumnCount()
	{
		return this.col;
	}

	public boolean checkAddress(GridAddress a)
	{
		return this.checkAddress(a.getRow(), a.getColumn());
	}

	public boolean checkAddress(int row, int col)
	{
		return row >= 0 && row < this.row && col >= 0 && col < this.col;
	}

	public boolean checkIndex(int index)
	{
		return index >= 0 && index < this.size;
	}

	public void rewind()
	{
		this.iterator = 0;
	}

	public boolean hasNext()
	{
		return this.iterator < this.size;
	}

	public E next()
	{
		return this.nodes.get(this.iterator++);
	}

	public int getSize()
	{
		return this.size;
	}

	public Integer getIndex(int row, int col)
	{
		if (this.checkAddress(row, col))
		{
			return col + row * this.row;
		}
		else
		{
			throw new GridAddressException(row, col);
		}
	}

	public GridAddress getAddress(int index)
	{
		if (this.checkIndex(index))
		{
			return new GridAddress(index / this.col, index % this.row);
		}
		else
		{
			throw new GridIndexException(index);
		}
	}

	public E getNode(int index)
	{
		if (this.checkIndex(index))
		{
			return this.nodes.get(index);
		}
		else
		{
			throw new GridIndexException(index);
		}
	}

	public E getNode(GridAddress a)
	{
		return this.getNode(a.row, a.column);
	}

	public E getNode(int row, int col)
	{
		if (this.checkAddress(row, col))
		{
			return this.nodes.get(this.getIndex(row, col));
		}
		else
		{
			throw new GridAddressException(row, col);
		}
	}

	public E setNode(int index, E node)
	{
		if (this.checkIndex(index))
		{
			node.row = index / this.col;
			node.col = index % this.row;
			node.index = index;

			return this.nodes.set(index, node);
		}
		else
		{
			throw new GridIndexException(index);
		}
	}

	public E setNode(int row, int col, E node)
	{
		if (this.checkAddress(row, col))
		{
			return this.setNode(this.getIndex(row, col), node);
		}
		else
		{
			throw new GridAddressException(row, col);
		}
	}
}
